package notify

import (
	"encoding/json"
	"enotify/pkg/notify/conf"
	"enotify/pkg/notify/provider/weixin"
	"fmt"
)

type WxIDao interface {
	GetAccessToken(appId string) (string,error)
}

type WxSender struct {
	c *conf.Config
	url string
	d WxIDao
	wx *weixin.WeiXin
}
func NewWxTemplateSender(c *conf.Config,d WxIDao) *WxSender{
	url := "https://api.weixin.qq.com/cgi-bin/message/template/send"
	return NewWxSender(c,d,url)
}
func NewWxCustomerSender(c *conf.Config,d WxIDao) *WxSender {
	url := "https://api.weixin.qq.com/cgi-bin/message/custom/send"
	return NewWxSender(c,d,url)
}

func NewWxSender(c *conf.Config,d WxIDao,url string) *WxSender{
	return &WxSender{
		c:   c,
		url: url,
		d:   d,
		wx: weixin.NewWeiXin(),
	}
}

func (s *Sender) SendWxTemplate(bizType string,msg TemplateMsg) error{
	data,_ :=msg.encode()
	task := Task{
		bizType: bizType,
		data:    data,
		sender:  s.wxTemplateSender,
	}
	return s.send(task)
}
func (s *Sender) SendWxCustomerWithText(bizType string,text customerWithText) error{
	data,_ := text.encode()
	task := Task{
		bizType: bizType,
		data:    data,
		sender:  s.wxCustomerSender,
	}
	return s.send(task)
}
func (s *Sender) SendWxCustomerWithImage(bizType string,image customerWithImage) error{
	data,_ := image.encode()
	task := Task{
		bizType: bizType,
		data:    data,
		sender:  s.wxCustomerSender,
	}
	return s.send(task)
}
func (s *Sender) SendWxCustomerWithNews(bizType string,news customerWithNews) error{
	data,_ := news.encode()
	task := Task{
		bizType: bizType,
		data:    data,
		sender:  s.wxCustomerSender,
	}
	return s.send(task)
}
func SenderWithWxTemplate(c *conf.Config,d WxIDao) option{
	return func(s *Sender) {
		s.wxTemplateSender = NewWxTemplateSender(c, d)
	}
}


func SenderWithWxCustomer(c *conf.Config,d WxIDao) option{
	return func(s *Sender) {
		s.wxCustomerSender = NewWxCustomerSender(c, d)
	}
}

func (w *WxSender) GetUrl(appId string)  (url string,err error){
	token, err := w.d.GetAccessToken(appId)
	if err != nil {
		return
	}
	url = fmt.Sprintf("%s?access_token=%s",w.url,token)
	return
}
func (w *WxSender) Send(bizType string,jn []byte) (reply *SendReply){
	var url string
	var err error
	reply = NewSendReply(0,"")
	if wxConf,ok := w.c.Wx[bizType]; ok {
		url,err = w.GetUrl(wxConf.AppId)
	} else {
		reply.Code = 10001
		reply.Msg = fmt.Sprintf("bizType:%s err",bizType)
		return
	}
	if err != nil {
		reply.Code = 10002
		reply.Msg = err.Error()
	}
	msgId,err := w.wx.SendWxCommonMsg(url,jn)
	if err != nil {
		reply.Code = 10001
		reply.Msg = err.Error()
		return reply
	}
	reply.Reply = msgId
	fmt.Println(url,err,string(jn))
	return
}
//模板消息
func NewTemplateMsg(touser, templateId,url string,keywords map[string]Keyworkd) TemplateMsg{
	return TemplateMsg{
		TemplateId: templateId,
		Touser: touser,
		Data: keywords,
		Url: url,
	}
}
//模板消息
func NewTemplateMsgWithMiniProgram(touser, templateId,url string,keywords map[string]Keyworkd,min Miniprogram) TemplateMsg{
	return TemplateMsg{
		TemplateId: templateId,
		Touser: touser,
		Data: keywords,
		Miniprogram: min,
		Url: url,
	}
}
type TemplateMsg struct {
	Touser      string `json:"touser"`
	TemplateId  string `json:"template_id"`
	Url         string `json:"url"`
	Miniprogram Miniprogram `json:"miniprogram"`
	Data map[string] Keyworkd `json:"data"`
}

func (t TemplateMsg) encode() ([]byte,error){
	data ,err := json.Marshal(t)
	return data,err
}


func NewKeyword(value,color string) Keyworkd{
	return  Keyworkd{
		Value: value,
		Color: color,
	}
}
type Keyworkd struct {
	Value string `json:"value"`
	Color string `json:"color"`
}

func NewMiniprogram(appid,pagepath string) Miniprogram{
	return Miniprogram{
		Appid:    appid,
		Pagepath: pagepath,
	}
}
type Miniprogram struct {
	Appid    string `json:"appid"`
	Pagepath string `json:"pagepath"`
}
//客服消息 文本
func NewCustomerWithText(touser string,content string) customerWithText {
	return customerWithText{
		Touser:  touser,
		Msgtype: "text",
		Text:    text{content},
	}
}
//客服消息 文本
type customerWithText struct {
	Touser  string `json:"touser"`
	Msgtype string `json:"msgtype"`
	Text   text`json:"text"`
}
func (t customerWithText) encode() ([]byte,error){
	data ,err := json.Marshal(t)
	return data,err
}
type text  struct {
	Content string `json:"content"`
}
//客服消息 图片
func NewCustomerWithImage(touser string,mediaId string) customerWithImage {
	return customerWithImage{
		Touser:  touser,
		Msgtype: "image",
		Image:    image{MediaId: mediaId},
	}
}
type customerWithImage struct {
	Touser  string `json:"touser"`
	Msgtype string `json:"msgtype"`
	Image  image `json:"image"`
}
type image struct {
	MediaId string `json:"media_id"`
}
func (t customerWithImage) encode() ([]byte,error){
	data ,err := json.Marshal(t)
	return data,err
}
//客服消息 图文
func NewCustomerWithNews(touser string,articles []article) customerWithNews {
	return customerWithNews{
		Touser:  touser,
		Msgtype: "news",
		News:    news{Articles: articles},
	}
}
type customerWithNews struct {
	Touser  string `json:"touser"`
	Msgtype string `json:"msgtype"`
	News news `json:"news"`
}
func (t customerWithNews) encode() ([]byte,error){
	data ,err := json.Marshal(t)
	return data,err
}
type news struct {
	Articles []article`json:"articles"`
}
type article struct {
	Title       string `json:"title"`
	Description string `json:"description"`
	Url         string `json:"url"`
	Picurl      string `json:"picurl"`
}
func NewActicle(title,desc,url,picurl string) article{
	return article{
		Title:       title,
		Description: desc,
		Url:         url,
		Picurl:      picurl,
	}
}
func NewActicles(arts ...article) []article{
	return arts
}